//GameClient - 游戏客户端
package Game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class GameClient extends Frame {
    public static final int WORLD_WIDTH = 1707;//游戏运行窗口的宽度
    public static final int WORLD_HEIGHT = 1067;//游戏运行窗口的高度
    private Image offScreenImage;//用于实现双缓冲绘图的Image对象，避免闪屏现象
    private World world;//游戏World类的实例
    private Thread paintThread; // 添加线程成员变量以控制线程
    private int isRemote=0;
    private int isMelee=0;


    //初始化游戏客户端
    public GameClient(boolean Doubleplayer){
        this.world = new World(WORLD_WIDTH, WORLD_HEIGHT, Doubleplayer);
        offScreenImage = null;
    }

    //对初始化游戏客户端的重构
    //新增两个int类型的变量
    //0则表示无选择
    //-1则表示单人模式下的选择
    //1则表示双人模式下的player1
    //2则表示双人模式下的player2
    public GameClient(boolean Doubleplayer,int isRemote,int isMelee)
    {
        this.isRemote=isRemote;
        this.isMelee=isMelee;
        this.world=new World(WORLD_WIDTH,WORLD_HEIGHT,Doubleplayer,isRemote,isMelee);
        offScreenImage=null;
    }



    //绘图线程
    private class PaintThread implements Runnable {
        //实现 Runnable接口，使实例可作为线程运行
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                if (world.End()) {
                    repaint();
                    showGameOverPanel(); // 游戏结束时直接显示结束面板
                    break;
                }
                repaint();
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }
    }

    //重置游戏
    private void resetWorld() {
        //停止旧线程并等待它结束
        if (paintThread != null && paintThread.isAlive()) {
            paintThread.interrupt();
            try {
                paintThread.join(); // 等待线程完全结束
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        // 移除旧的键盘监听器，以防止重复添加
        for (KeyListener kl : this.getKeyListeners()) {
            this.removeKeyListener(kl);
        }

        // 创建一个新的World实例，以清除之前的游戏状态
        this.world = new World(WORLD_WIDTH, WORLD_HEIGHT, this.world.isDoublePlayer(),isRemote,isMelee);
        offScreenImage = null;

        //添加键盘监听器
        if(!world.isDoublePlayer())//单人情况
        {
            if(isRemote==-1&&isMelee==0)
            {
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(0)));//单人远程
            }
            else
            {
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(0)));//单人近战
            }
        }
        else
        {
            if(isRemote==1&&isMelee==0)//双远程
            {
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(0)));
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(1)));
            }
            else if(isRemote==1&&isMelee==2)//玩家1为远程，玩家2为近战
            {
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(0)));
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(1)));
            }
            else if(isRemote==2&&isMelee==1)//玩家1为近战，玩家2为远程
            {
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(0)));
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(1)));
            }
            else//双近战
            {
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(0)));
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(1)));
            }
        }

        this.requestFocus();

        //启动重绘线程：创建并启动一个新线程，运行 PaintThread 类的实例
        paintThread = new Thread(new PaintThread());
        paintThread.start();

    }

    //结束画面添加重新开始按钮和返回主界面按钮
    public void showGameOverPanel() {
        // 创建一个面板
        Panel gameOverPanel = new Panel();
        gameOverPanel.setLayout(new GridLayout(2, 1)); // 两行一列的布局

        // 创建按钮
        ImageIcon restartIcon = new ImageIcon(Start.class.getResource("/images/restart.png"));
        restartIcon.setImage(restartIcon.getImage().getScaledInstance(380,140,Image.SCALE_DEFAULT));//将图标缩放到指定的宽度和高度
        JButton restartButton = new JButton(restartIcon);

        ImageIcon returnMainMenuIcon = new ImageIcon(Start.class.getResource("/images/returnMainMenu.png"));
        returnMainMenuIcon.setImage(returnMainMenuIcon.getImage().getScaledInstance(380,140,Image.SCALE_DEFAULT));//将图标缩放到指定的宽度和高度
        JButton returnMainMenuButton = new JButton(returnMainMenuIcon);

        // 将按钮添加到面板
        gameOverPanel.add(restartButton);
        gameOverPanel.add(returnMainMenuButton);

        // 在游戏结束时显示面板
        this.add(gameOverPanel);
        this.setLocationRelativeTo(null); // 居中显示
        gameOverPanel.setVisible(true);

        // 确保面板刷新
        revalidate();
        repaint();


        // 为按钮添加事件监听器
        restartButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 停止绘图线程
                if (paintThread != null && paintThread.isAlive()) {
                    paintThread.interrupt();
                    try {
                        paintThread.join(); // 等待线程完全结束
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }

                // 隐藏游戏结束面板
                gameOverPanel.setVisible(false);
                remove(gameOverPanel);
                revalidate();
                repaint();

                resetWorld();

            }
        });

        returnMainMenuButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 停止绘图线程
                if (paintThread != null && paintThread.isAlive()) {
                    paintThread.interrupt();
                    try {
                        paintThread.join(); // 等待线程完全结束
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                setVisible(false);
                new Start();
            }
        });


    }

    //绘制游戏界面
    public void paint(Graphics g) {
    	if(!world.End())
    		world.drawWorld(g);
    	else {
    		world.drawEnd(g);
    	}
    }

    //双缓冲绘图，避免闪屏
    //repaint()隐式调用该方法
    public void update(Graphics g) {
        //检查是否有离屏图像，如果没则创建一个
        if(offScreenImage == null) {
            offScreenImage = this.createImage(WORLD_WIDTH, WORLD_HEIGHT);//创建离屏图像
        }
        Graphics gOffScreen = offScreenImage.getGraphics();//获取离屏图像
        Color c = gOffScreen.getColor();//保存当前的绘图颜色
        gOffScreen.setColor(Color.lightGray);//离屏图像的绘图颜色设置为 Color.lightGray
        gOffScreen.fillRect(0, 0, WORLD_WIDTH, WORLD_HEIGHT);//用浅灰色填充整个离屏图像的背景
        gOffScreen.setColor(c);//恢复原颜色: 将绘图颜色恢复为之前保存的颜色 c，确保接下来的绘制操作不会受到背景填充颜色的影响。
        paint(gOffScreen);//调用paint()方法，在离屏图像上绘制图形
        g.drawImage(offScreenImage, 0, 0, null);//将离屏图像绘制到屏幕上
    }

    //初始化并启动游戏窗口
    public void lauchFrame() {
        this.setLocation(0, 0);//放置窗口位置
        this.setSize(WORLD_WIDTH, WORLD_HEIGHT);//设置窗口大小
        this.setTitle("ZombieCrisis");//设置窗口标题
        //设置窗口监听器
        this.addWindowListener(new WindowAdapter() {
            //WindowAdapter类 - 监听窗口事件

            //关闭窗口时调用的方法
            public void windowClosing(WindowEvent e) {
                System.exit(0);//程序正常退出
            }
        });
        this.setResizable(false); //禁止调整窗口大小
        this.setBackground(Color.lightGray);//设置窗口背景颜色 - 浅灰

        /*
        //添加键盘监听器
        //给第一个角色对象添加键盘监听器
        this.addKeyListener(new KeyMonitor((Hero) world.getObject(0)));
        //检查第二个角色对象是否存在，存在则也给这个对象添加键盘监听器
        if(world.getObject(1) instanceof Hero)
            this.addKeyListener(new KeyMonitor((Hero) world.getObject(1)));

         */


        //添加键盘监听器
        if(!world.isDoublePlayer())//单人情况
        {
            if(isRemote==-1&&isMelee==0)
            {
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(0)));//单人远程
            }
            else
            {
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(0)));//单人近战
            }
        }
        else
        {
            if(isRemote==1&&isMelee==0)//双远程
            {
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(0)));
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(1)));
            }
            else if(isRemote==1&&isMelee==2)//玩家1为远程，玩家2为近战
            {
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(0)));
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(1)));
            }
            else if(isRemote==2&&isMelee==1)//玩家1为近战，玩家2为远程
            {
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(0)));
                this.addKeyListener(new KeyMonitorRemote((Remote) world.getObject(1)));
            }
            else//双近战
            {
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(0)));
                this.addKeyListener(new KeyMonitorMelee((Melee) world.getObject(1)));
            }
        }

        setVisible(true);//设置窗口为可见

        //启动重绘线程：创建并启动一个新线程，运行 PaintThread 类的实例
        paintThread = new Thread(new PaintThread());
        paintThread.start();
    }

    //处理键盘输入事件
    private class KeyMonitor extends KeyAdapter {
        Hero hero;//创键角色实例

        //有参构造方法 - 传入Hero实例
        public KeyMonitor(Hero hero){
            this.hero = hero;
        }

        public void keyReleased(KeyEvent e) {
            this.hero.keyReleased(e);
        }//处理玩家的释放动作

        public void keyPressed(KeyEvent e) {
            this.hero.KeyPressed(e);
        }//处理玩家的按键动作
    }
    //处理Remote键盘输入事件
    private class KeyMonitorRemote extends KeyAdapter
    {
        Remote remote;////创键角色实例

        public KeyMonitorRemote(Remote remote)
        {
            this.remote=remote;
        }

        public void keyReleased(KeyEvent e)
        {
            this.remote.keyReleased(e);
        }//处理玩家的释放动作

        public void keyPressed(KeyEvent e)
        {
            this.remote.KeyPressed(e);
        }//处理玩家的按键动作
    }
    ////处理Melee键盘输入事件
    private class KeyMonitorMelee extends KeyAdapter
    {
        Melee melee;

        public KeyMonitorMelee(Melee melee)
        {
            this.melee=melee;
        }

        public void keyReleased(KeyEvent e)
        {
            this.melee.keyReleased(e);
        }

        public void keyPressed(KeyEvent e)
        {
            this.melee.KeyPressed(e);
        }
    }
}
